package com.cershy.chatroomserver.utils;

/**
 * Snowflake ID 生成器
 */
public class SnowflakeIdGenerator {

    // 每一部分占用的位数
    private final long nodeId;
    private long lastTimestamp = -1L;
    private long lastId = 0L;

    private static final long NODE_BITS = 10L;       // 节点部分所占位数
    private static final long SEQUENCE_BITS = 12L;   // 序列号部分所占位数

    private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS); // 最大序列号：4095

    // 节点掩码（用于防止越界）
    private static final long NODE_MASK = ~(-1L << NODE_BITS) << SEQUENCE_BITS;
    private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);

    // 时间戳偏移量（从2023-01-01开始计算）
    private static final long NODE_SHIFT = SEQUENCE_BITS;
    private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + NODE_BITS;

    public SnowflakeIdGenerator(long nodeId) {
        if (nodeId < 0 || nodeId > ((1 << NODE_BITS) - 1)) {
            throw new IllegalArgumentException("Node ID 必须在 0 到 " + ((1 << NODE_BITS) - 1) + " 之间");
        }
        this.nodeId = nodeId << SEQUENCE_BITS;
    }

    /**
     * 获取下一个ID
     */
    public synchronized Long nextId() {
        long timestamp = System.currentTimeMillis();

        if (timestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨: " + (lastTimestamp - timestamp));
        }

        if (timestamp == lastTimestamp) {
            // 同一毫秒内生成ID
            lastId = (lastId + 1) & MAX_SEQUENCE;
            if (lastId == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            // 新的一毫秒，重置序列号
            lastId = 0;
        }

        lastTimestamp = timestamp;

        return (timestamp << TIMESTAMP_SHIFT)
                | nodeId
                | lastId;
    }

    /**
     * 等待到下一毫秒
     */
    private long tilNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }
}
